package com.xiaowu.netmusic.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaowu.netmusic.common.exception.OAuth2Exception;
import com.xiaowu.netmusic.common.properties.GithubAppProperties;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class GithubOAuth2Service {

    private final GithubAppProperties githubAppProperties;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    public String getAccessToken(String code) {
        if (!StringUtils.hasText(code)) {
            throw new OAuth2Exception("Authorization code cannot be empty");
        }

        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("client_id", githubAppProperties.getClientId());
        params.add("client_secret", githubAppProperties.getClientSecret());
        params.add("code", code);
        params.add("redirect_uri", githubAppProperties.getRedirectUri());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);

        try {
            ResponseEntity<String> response = restTemplate.exchange(
                    githubAppProperties.getTokenUri(),
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );

            if (!response.getStatusCode().is2xxSuccessful()) {
                log.error("Failed to get access token. Response: {}", response.getBody());
                throw new OAuth2Exception("Failed to get access token from GitHub");
            }

            return parseAccessToken(response.getBody());
        } catch (Exception e) {
            log.error("Error while getting access token from GitHub", e);
            throw new OAuth2Exception("Failed to get access token from GitHub", e);
        }
    }

    public Map<String, Object> getUserInfo(String accessToken) {
        if (!StringUtils.hasText(accessToken)) {
            throw new OAuth2Exception("Access token cannot be empty");
        }

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + accessToken);
        HttpEntity<String> entity = new HttpEntity<>(headers);

        try {
            ResponseEntity<String> response = restTemplate.exchange(
                    githubAppProperties.getUserInfoUri(),
                    HttpMethod.GET,
                    entity,
                    String.class
            );

            if (!response.getStatusCode().is2xxSuccessful()) {
                log.error("Failed to get user info. Response: {}", response.getBody());
                throw new OAuth2Exception("Failed to get user info from GitHub");
            }

            return parseUserInfo(response.getBody());
        } catch (Exception e) {
            log.error("Error while getting user info from GitHub", e);
            throw new OAuth2Exception("Failed to get user info from GitHub", e);
        }
    }

    private String parseAccessToken(String responseBody) {
        try {
            // 先尝试解析为JSON（如果设置了Accept头）
            try {
                JsonNode jsonNode = objectMapper.readTree(responseBody);
                JsonNode tokenNode = jsonNode.get("access_token");
                if (tokenNode != null) {
                    return tokenNode.asText();
                }
            } catch (JsonProcessingException e) {
                // 如果不是JSON，尝试解析为URL编码格式
                log.debug("Response is not JSON, trying URL encoded format");
            }

            // 解析URL编码格式
            String[] pairs = responseBody.split("&");
            for (String pair : pairs) {
                String[] keyValue = pair.split("=");
                if (keyValue.length == 2 && "access_token".equals(keyValue[0])) {
                    return keyValue[1];
                }
            }

            throw new OAuth2Exception("Access token not found in response");
        } catch (Exception e) {
            log.error("Failed to parse access token from response: {}", responseBody, e);
            throw new OAuth2Exception("Failed to parse access token", e);
        }
    }

    private Map<String, Object> parseUserInfo(String responseBody) {
        try {
            return objectMapper.readValue(responseBody, Map.class);
        } catch (Exception e) {
            log.error("Failed to parse user info from response: {}", responseBody, e);
            throw new OAuth2Exception("Failed to parse user info", e);
        }
    }
}
